var co = require('co');
var express = require('express');
var router = express.Router();
// var block = require('../block');
var msg = require('../config/responseMsg');
var log = require('../config/log4jsConfig');
var config = require('../config/baseConfig');
var channelUtil = require('../service/channel');
// var URL = require('url');

var rspErr = '{"status":"ERROR"}';
var rspSucc = '{"status":"OK"}';

var resSucc = {
  status: 'OK'
};

var resErr = {
  status: 'ERROR'
}

var org = config.ORG;
var peer = config.PEER;
var ordererOrg = config.ORDERER_ORG;
var ordererId = config.ORDERER_ID;
// var chaincodePath = config.CHAINCODE_PATH;
var chaincodeVersion = config.CHAINCODE_VERSION;
// var channelName = config.CHANNEL_NAME;
// var chaincodeId = config.CHAINCODE_ID;

router.post('/', function (req, res, next) {
  log.debug(JSON.stringify(req.body));
  // 根据json格式报文，调用方法


  if (!req.body) {
    log.error(msg.NOT_FOUND_REQUEST_BODY);
    return res.sendStatus(400);
  }

  var method = req.body.method;
  var params = req.body.params;
  if (!method) {
    log.error(msg.NOT_FOUND_METHOD);
    resErr.msg = msg.NOT_FOUND_METHOD;
    return res.send(resErr);
  }
  if (!params) {
    log.error(msg.NOT_FOUNT_PARAMS);
    resErr.msg = msg.NOT_FOUNT_PARAMS;
    return res.send(resErr);
  }
  var chaincode = params.chaincodeID;
  var ctorMsg = params.ctorMsg;
  if (!ctorMsg) {
    return res.send(resErr);
  }
  var functionName = ctorMsg.function; //savetocbsp
  var args = ctorMsg.args;

  channelName = chaincode.channelName;
  chaincodeId = chaincode.name;
  var fcn = functionName;
  chaincodePath = chaincode.path;

  if(chaincode.version){
    chaincodeVersion = chaincode.version;
  }

  if ("operateChannel" === method && "create" === functionName) {
    createChannel(res, channelName, ordererOrg, ordererId);
  } else if ("operateChannel" === method && "join" === functionName) {
    joinChannel(res, org, peer, ordererOrg, ordererId, channelName);
  } else if ("deploy" === method && "install" === functionName) {
    install(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName);
  } else if ("deploy" === method && "instantiate" === functionName) {
    instantiate(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args);
  } else if ("deploy" === method && "upgrade" === functionName) {
    upgrade(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args, "upgrade");
  } else if ("query" === method) {
    query(res, org, peer, ordererOrg, ordererId, chaincodeVersion, fcn, args, chaincodeId, channelName);
  }
  if ("invoke" === method) {
    invoke(res, org, peer, ordererOrg, ordererId, chaincodeVersion, chaincodeId, channelName, fcn, args);
  } else if ("block" === method && "getBlock" === functionName) {
    var blockNumber = args[0];
    getBlock(res, channelName, org, peer, ordererOrg, ordererId, blockNumber);
  } else if ("block" === method && "getBlockByHash" === functionName) {
    var blockHash = args[0];
    getBlockByHash(res, channelName, org, peer, ordererOrg, ordererId, blockHash);
  } else if ("block" === method && "queryTransaction" === functionName) {
    var tx_id = args[0];
    queryTransaction(res, channelName, org, peer, ordererOrg, ordererId, tx_id);
  } else if ("block" === method && "queryInfo" === functionName) {
    queryInfo(res, channelName, org, peer, ordererOrg, ordererId);
  } else if ("block" === method && "queryInstalledChaincodes" === functionName) {
    queryInstalledChaincodes(res, channelName, org, peer, ordererOrg, ordererId);
  } else if ("block" === method && "queryInstantiatedChaincodes" === functionName) {
    queryInstantiatedChaincodes(res, channelName, org, peer, ordererOrg, ordererId);
  } else if ("block" === method && "queryChannels" === functionName) {
    queryChannels(res, channelName, org, peer, ordererOrg, ordererId);
  } else if ("block" === method && "getPeers" === functionName) {
    getPeers(res, channelName, org, peer, ordererOrg, ordererId);
  }

  // res.send(resSucc);
});


function createChannel(res, channelName, ordererOrg, ordererId) {
  co(function* () {
    log.info('/createchannel');
    var result = yield channelUtil.createChannel(channelName, ordererOrg, ordererId);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function joinChannel(res, org, peer, ordererOrg, ordererId, channelName) {
  co(function* () {
    log.info('/joinChannel');
    var result = yield channelUtil.joinChannel(org, peer, ordererOrg, ordererId, channelName);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function install(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName) {
  co(function* () {
    log.info('/install');
    var result = yield channelUtil.installChaincode(org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function instantiate(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args) {
  co(function* () {
    log.info('/instantiate');
    var result = yield channelUtil.instantiateChaincode(org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function upgrade(res, org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args, upgrade) {
  co(function* () {
    log.info('/upgrade');
    var result = yield channelUtil.instantiateChaincode(org, peer, ordererOrg, ordererId, chaincodePath, chaincodeVersion, chaincodeId, channelName, args, upgrade);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function query(res, org, peer, ordererOrg, ordererId, chaincodeVersion, fcn, args, chaincodeId, channelName) {
  co(function* () {
    log.info('/query');
    var result = yield channelUtil.queryCc(org, peer, ordererOrg, ordererId, chaincodeVersion, fcn, args, chaincodeId, channelName);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function invoke(res, org, peer, ordererOrg, ordererId, chaincodeVersion, chaincodeId, channelName, fcn, args) {
  co(function* () {
    log.info('/invoke');
    var result = null;
    if (config.LISTEN_TRANSACTION_EVENTS) {
      result = yield channelUtil.sendTransaction(org, peer, ordererOrg, ordererId, chaincodeVersion, chaincodeId, channelName, fcn, args);
    } else {
      result = yield channelUtil.noEventHubSendTransaction(org, peer, ordererOrg, ordererId, chaincodeVersion, chaincodeId, channelName, fcn, args);
    }
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function getBlock(res, channelName, org, peer, ordererOrg, ordererId, blockNumber) {
  co(function* () {
    log.info('/getBlock');
    var result = yield channelUtil.getblockInfobyNum(channelName, org, peer, ordererOrg, ordererId, blockNumber);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function getBlockByHash(res, channelName, org, peer, ordererOrg, ordererId, blockHash) {
  co(function* () {
    log.info('/getBlockByHash');
    var result = yield channelUtil.getblockInfobyHash(channelName, org, peer, ordererOrg, ordererId, blockHash);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function queryTransaction(res, channelName, org, peer, ordererOrg, ordererId, tx_id) {
  co(function* () {
    log.info('/queryTransaction');
    var result = yield channelUtil.getblockInfobyTxId(channelName, org, peer, ordererOrg, ordererId, tx_id);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function queryInfo(res, channelName, org, peer, ordererOrg, ordererId) {
  co(function* () {
    log.info('/queryInfo');
    var result = yield channelUtil.getBlockChainInfo(channelName, org, peer, ordererOrg, ordererId);
    log.debug(result.height.toString());
    res.send(JSON.stringify(result.height.toString()));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function queryInstalledChaincodes(res, channelName, org, peer, ordererOrg, ordererId) {
  co(function* () {
    log.info('/queryInstalledChaincodes');
    var result = yield channelUtil.getPeerInstallCc(channelName, org, peer, ordererOrg, ordererId);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function queryInstantiatedChaincodes(res, channelName, org, peer, ordererOrg, ordererId) {
  co(function* () {
    log.info('/queryInstantiatedChaincodes');
    var result = yield channelUtil.getPeerInstantiatedCc(channelName, org, peer, ordererOrg, ordererId);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function queryChannels(res, channelName, org, peer, ordererOrg, ordererId) {
  co(function* () {
    log.info('/queryChannels');
    var result = yield channelUtil.getPeerChannel(channelName, org, peer, ordererOrg, ordererId);
    log.debug(result);
    res.send(JSON.stringify(result));
  }).catch((err) => {
    log.error('Error stack : \n %s ', err.stack);
    res.send(err.stack);
  });
}

function getPeers(res, channelName, org, peer, ordererOrg, ordererId) {

}

module.exports = router;